package com.xiang.ad.service;

import com.alibaba.fastjson.JSON;
import com.xiang.ad.Application;
import com.xiang.ad.constant.CommonStatus;
import com.xiang.ad.dao.AdPlanRepository;
import com.xiang.ad.dao.AdUnitRepository;
import com.xiang.ad.dao.CreativeRepository;
import com.xiang.ad.dao.unit_condition.AdUnitDistrictRepository;
import com.xiang.ad.dao.unit_condition.AdUnitItRepository;
import com.xiang.ad.dao.unit_condition.AdUnitKeywordRepository;
import com.xiang.ad.dao.unit_condition.CreativeUnitRepository;
import com.xiang.ad.dump.DConstant;
import com.xiang.ad.dump.table.*;
import com.xiang.ad.entity.AdPlan;
import com.xiang.ad.entity.AdUnit;
import com.xiang.ad.entity.Creative;
import com.xiang.ad.entity.unit_condition.AdUnitDistrict;
import com.xiang.ad.entity.unit_condition.AdUnitIt;
import com.xiang.ad.entity.unit_condition.AdUnitKeyword;
import com.xiang.ad.entity.unit_condition.CreativeUnit;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by xiang.
 * 实现导出服务
 * 将数据库中的数据表的记录导出到文件中，目的是为了能够在检索服务中实现数据的加载，构造全量索引
 * 一个默认的Spring Boot项目中就自动生成了测试类，其中的注解就有 @RunWith 和 @SpringBootTest
 */
@Slf4j
@RunWith(SpringRunner.class)   //SpringRunner  这是测试用例的标记，也是 SpringBoot 所规定的。
@SpringBootTest(classes = {Application.class}, //标记为SpringBoot的测试用例
        webEnvironment = SpringBootTest.WebEnvironment.NONE) //不需要外部环境，只需要访问数据库
public class DumpDataService {

    //将各个表的dao接口导入进来，方便接下来各个表的导出
    @Autowired
    private AdPlanRepository planRepository;//计划
    @Autowired
    private AdUnitRepository unitRepository;//单元
    @Autowired
    private CreativeRepository creativeRepository;//创意
    @Autowired
    private CreativeUnitRepository creativeUnitRepository;//创意&推广单元

    @Autowired
    private AdUnitKeywordRepository keywordRepository;//推广单元关键词限制
    @Autowired
    private AdUnitDistrictRepository districtRepository;//推广单元地域限制
    @Autowired
    private AdUnitItRepository itRepository;//推广单元兴趣限制




    //导出文件的test文件
    @Test
    public void dumpAdTableData() {

        dumpAdPlanTable(
                String.format("%s%s", DConstant.DATA_ROOT_DIR,  //导出目录路径
                        DConstant.AD_PLAN)                      //
        );
        dumpAdUnitTable(
                String.format("%s%s", DConstant.DATA_ROOT_DIR,
                        DConstant.AD_UNIT)
        );
        dumpAdCreativeTable(
                String.format("%s%s", DConstant.DATA_ROOT_DIR,
                        DConstant.AD_CREATIVE)
        );
        dumpAdCreativeUnitTable(
                String.format("%s%s", DConstant.DATA_ROOT_DIR,
                        DConstant.AD_CREATIVE_UNIT)
        );
        dumpAdUnitDistrictTable(
                String.format("%s%s", DConstant.DATA_ROOT_DIR,
                        DConstant.AD_UNIT_DISTRICT)
        );
        dumpAdUnitItTable(
                String.format("%s%s", DConstant.DATA_ROOT_DIR,
                        DConstant.AD_UNIT_IT)
        );
        dumpAdUnitKeywordTable(
                String.format("%s%s", DConstant.DATA_ROOT_DIR,
                        DConstant.AD_UNIT_KEYWORD)
        );
    }


    /**
     * 1、从数据库表中获取到这张表的所有（有效）数据,获取想要的全量数据
     * 2、根据数据表中的记录 对应的转换为 需要这些字段属性的java类上（xxxtable），实现转换
     * 3、将转换完成的list对象（xxxTable）数据遍历以json的格式逐行写入到文件中
     * 文件中每一行都是一个json数据，里面包含了在adPlanTable中定义的各个属性，也就是构造索引时候所需要的各个属性
     *
     * XXTable 标识的是对表结构的声明，是对数据表的 Java Object 描述
     * XXObject 标识的是对索引对象的声明，是与索引架构有关的描述
     */
    // 导出 推广计划
    private void dumpAdPlanTable(String fileName) { //fileName为文件导出到哪里

        //获取adPlan
        List<AdPlan> adPlans = planRepository.findAllByPlanStatus(
                CommonStatus.VALID.getStatus() //根据状态导出，有效状态的计划才导出
        );
        if (CollectionUtils.isEmpty(adPlans)) {//如果没有获取到adPlan，也就不需要导出数据了
            return;
        }

        //
        List<AdPlanTable> planTables = new ArrayList<>();
        adPlans.forEach(p -> planTables.add(   //各个adPlan转化成PlanTable，就是往planTable中增加记录
                new AdPlanTable(
                        p.getId(), //plan的id
                        p.getUserId(), //plan归属的user的id
                        p.getPlanStatus(),//plan的状态
                        p.getStartDate(),//plan的开始时间
                        p.getEndDate()//plan的结束时间
                )
        ));

        //获取路径 导入文件
        Path path = Paths.get(fileName);
        try (BufferedWriter writer = Files.newBufferedWriter(path)) {
            for (AdPlanTable planTable : planTables) { //遍历刚才填入的planTable
                writer.write(JSON.toJSONString(planTable)); //写入文件，序列化成json数据
                writer.newLine(); //写新的行
            }
            writer.close();
        } catch (IOException ex) {
            log.error("导出AdPlanTable error");
        }
    }

    //导出 推广单元
    private void dumpAdUnitTable(String fileName) {

        ////获取有效状态的adPlan
        List<AdUnit> adUnits = unitRepository.findAllByUnitStatus(
                CommonStatus.VALID.getStatus()
        );
        if (CollectionUtils.isEmpty(adUnits)) {//如果当前有效的推广单元是空的
            return;
        }

        //遍历adUnits，将各个字段填入unitTables
        List<AdUnitTable> unitTables = new ArrayList<>();
        adUnits.forEach(u -> unitTables.add(
                new AdUnitTable(
                        u.getId(),//推广单元id
                        u.getUnitStatus(),//推广单元状态
                        u.getPositionType(),//广告位类型(开屏, 贴片, 中贴,暂停贴，后贴...)
                        u.getPlanId() //关联的 推广计划  的id
                )
        ));

        //获取路径  导入文件
        Path path = Paths.get(fileName);
        try (BufferedWriter writer = Files.newBufferedWriter(path)) {
            for (AdUnitTable unitTable : unitTables) {//遍历
                writer.write(JSON.toJSONString(unitTable));//写入文件，将上面推广单元的各个字段序列化成json格式
                writer.newLine();//写新的行
            }
            writer.close();
        } catch (IOException ex) {
            log.error("dumpAdUnitTable error");
        }
    }

    //导出 创意
    private void dumpAdCreativeTable(String fileName) {

        //尝试获取当前数据库中 所有创意
        List<Creative> creatives = creativeRepository.findAll();
        if (CollectionUtils.isEmpty(creatives)) {
            return;
        }

        //遍历 填充创意属性
        List<AdCreativeTable> creativeTables = new ArrayList<>();
        creatives.forEach(c -> creativeTables.add(
                new AdCreativeTable(
                        c.getId(), //创意id
                        c.getName(),//创意名字
                        c.getType(),//创意类型
                        c.getMaterialType(),//创意的子类型
                        c.getHeight(),//高度
                        c.getWidth(),//宽度
                        c.getAuditStatus(),//创意的审核状态
                        c.getUrl()//创意的url
                )
        ));

        //遍历写入文件，序列化成json格式
        Path path = Paths.get(fileName);
        try (BufferedWriter writer = Files.newBufferedWriter(path)) {
            for (AdCreativeTable creativeTable : creativeTables) {
                writer.write(JSON.toJSONString(creativeTable));//写入文件，json
                writer.newLine();
            }
            writer.close();
        } catch (IOException ex) {
            log.error("dumpAdCreativeTable error");
        }
    }

    //创意&推广单元的关联表 导出
    private void dumpAdCreativeUnitTable(String fileName) {

        List<CreativeUnit> creativeUnits = creativeUnitRepository.findAll();
        if (CollectionUtils.isEmpty(creativeUnits)) {
            return;
        }

        List<AdCreativeUnitTable> creativeUnitTables = new ArrayList<>();
        creativeUnits.forEach(c -> creativeUnitTables.add(
                new AdCreativeUnitTable(
                        c.getCreativeId(),
                        c.getUnitId()
                )
        ));

        Path path = Paths.get(fileName);
        try (BufferedWriter writer = Files.newBufferedWriter(path)) {
            for (AdCreativeUnitTable creativeUnitTable : creativeUnitTables) {
                writer.write(JSON.toJSONString(creativeUnitTable));
                writer.newLine();
            }
            writer.close();
        } catch (IOException ex) {
            log.error("dumpAdCreativeUnit error");
        }
    }

    //推广单元 地域限制
    private void dumpAdUnitDistrictTable(String fileName) {

        //1、从数据库中获取全量数据
        List<AdUnitDistrict> unitDistricts = districtRepository.findAll();
        if (CollectionUtils.isEmpty(unitDistricts)) {
            return;
        }

        //2、实现转换
        List<AdUnitDistrictTable> unitDistrictTables = new ArrayList<>();
        unitDistricts.forEach(d -> unitDistrictTables.add(
                new AdUnitDistrictTable(
                        d.getUnitId(),
                        d.getProvince(),
                        d.getCity()
                )
        ));

        //3、写入数据到文件中
        Path path = Paths.get(fileName);
        try (BufferedWriter writer = Files.newBufferedWriter(path)) {
            for (AdUnitDistrictTable unitDistrictTable : unitDistrictTables) {
                writer.write(JSON.toJSONString(unitDistrictTable));
                writer.newLine();
            }
            writer.close();
        } catch (IOException ex) {
            log.error("dumpAdUnitDistrictTable error");
        }
    }

    //推广单元 兴趣导出
    private void dumpAdUnitItTable(String fileName) {

        //1、从数据库中获取全量数据
        List<AdUnitIt> unitIts = itRepository.findAll();
        if (CollectionUtils.isEmpty(unitIts)) {
            return;
        }

        //2、实现转换
        List<AdUnitItTable> unitItTables = new ArrayList<>();
        unitIts.forEach(i -> unitItTables.add(
                new AdUnitItTable(
                        i.getUnitId(),
                        i.getItTag()
                )
        ));

        //3、写入数据到文件中
        Path path = Paths.get(fileName);
        try (BufferedWriter writer = Files.newBufferedWriter(path)) {
            for (AdUnitItTable unitItTable : unitItTables) {
                writer.write(JSON.toJSONString(unitItTable));
                writer.newLine();
            }
            writer.close();
        } catch (IOException ex) {
            log.error("dumpAdUnitItTable error");
        }
    }

    //推广单元 关键词导出
    private void dumpAdUnitKeywordTable(String fileName) {

        //1、从数据库中获取全量数据
        List<AdUnitKeyword> unitKeywords = keywordRepository.findAll();
        if (CollectionUtils.isEmpty(unitKeywords)) {
            return;
        }

        //2、实现转换
        List<AdUnitKeywordTable> unitKeywordTables = new ArrayList<>();
        unitKeywords.forEach(k -> unitKeywordTables.add(
                new AdUnitKeywordTable(
                        k.getUnitId(),
                        k.getKeyword()
                )
        ));

        //3、写入数据到文件中
        Path path = Paths.get(fileName);
        try (BufferedWriter writer = Files.newBufferedWriter(path)) {
            for (AdUnitKeywordTable unitKeywordTable : unitKeywordTables) {
                writer.write(JSON.toJSONString(unitKeywordTable));
                writer.newLine();
            }
            writer.close();
        } catch (IOException ex) {
            log.error("dumpAdUnitItTable error");
        }
    }
}
